import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ExecutionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wangweiqiang
 * @version 1.0
 * @date 2021-08-16 20:28
 */
public class Advanced {
    @Test
    public void testBusinessKey(){
        final ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        final RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
        final ProcessInstance instance = runtimeService.startProcessInstanceByKey("evection", "12345");

        System.out.println("业务id："+instance.getBusinessKey());
    }


    @Test
    public void testQueryInstanceState(){
        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final RuntimeService runtimeService = processEngine.getRuntimeService();

        final ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery();
        final ProcessInstanceQuery instanceQuery = processInstanceQuery.processDefinitionKey("evection");
        final List<ProcessInstance> processInstances = instanceQuery.list();
        for (ProcessInstance processInstance : processInstances) {
            System.out.println("----------------------------");
            System.out.println("流程实例id："
                    + processInstance.getProcessInstanceId());
            System.out.println("所属流程定义id："
                    + processInstance.getProcessDefinitionId());
            System.out.println("是否执行完成：" + processInstance.isEnded());
            System.out.println("是否暂停：" + processInstance.isSuspended());
            System.out.println("当前活动标识：" + processInstance.getActivityId());
            System.out.println("BusinessKey：" + processInstance.getBusinessKey());
        }


        final ExecutionQuery executionQuery = runtimeService.createExecutionQuery();
        final List<Execution> list = executionQuery.executionId("42501").list();
        for (Execution execution : list) {
            System.out.println(execution.getProcessInstanceId());
            System.out.println(execution.getName());
        }
    }

    @Test
    public void testSuspendAllInstancesOfDefinition(){
        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final RepositoryService repositoryService = processEngine.getRepositoryService();

        final ProcessDefinition myEvection = repositoryService.createProcessDefinitionQuery().processDefinitionKey("myEvection").singleResult();

        final boolean suspended = myEvection.isSuspended();

        if (suspended){
            //如果myEvection流程定义的所有实例都被刮起了，则重新激活
            repositoryService.activateProcessDefinitionByKey("myEvection",true,null);

            System.out.println("流程定义【"+myEvection.getId()+"】已激活");
        }else {
            //如果myEvection流程定义的所有实例都是激活状态，则全部挂起
            repositoryService.suspendProcessDefinitionByKey("myEvection",true,null);
            System.out.println("流程定义【"+myEvection.getId()+"】已挂起");
        }
    }

    @Test
    public void testSuspendSomeOneInstanceOfDefinition(){
        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final RuntimeService runtimeService = processEngine.getRuntimeService();

        final ProcessInstanceQuery instanceQuery = runtimeService.createProcessInstanceQuery();

        final ProcessInstance processInstance = instanceQuery.processInstanceId("32501").singleResult();

        final boolean suspended = processInstance.isSuspended();
        if (suspended){
            //如果该实例被挂起则重新激活
            runtimeService.activateProcessInstanceById(processInstance.getId());

            System.out.println("流程实例："+processInstance.getId()+",已激活");

        }else {
            //如果该实例是激活状态则挂起
            runtimeService.suspendProcessInstanceById(processInstance.getId());
            System.out.println("流程实例："+processInstance.getId()+",已挂起");


        }
    }

    @Test
    public void testCompleteTask(){
        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final TaskService taskService = processEngine.getTaskService();
        final List<Task> list = taskService.createTaskQuery().processDefinitionKey("evection").taskAssignee("jerry").list();

        for (Task task : list) {
            taskService.complete(task.getId());
            //org.activiti.engine.ActivitiException: Cannot complete a suspended task
            System.out.println(task.getId());
            System.out.println(task.isSuspended());
        }
    }

    @Test
    public void testStartProcess() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();


        //创建流程实例是动态指定处理人
        Map<String,Object> assigneeMap = new HashMap<>();
        assigneeMap.put("assignee0","张三");
        assigneeMap.put("assignee1","李经理");
        assigneeMap.put("assignee2","王总经理");
        assigneeMap.put("assignee3","赵财务");

        final ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("evection2",assigneeMap);


        System.out.println("流程部署id：" + processInstance.getId());
        System.out.println("流程定义id：" + processInstance.getProcessDefinitionId());
        System.out.println("当前活动id：" + processInstance.getActivityId());
    }


    //以下测试监听器

    /**
     * 发布一个流程定义,插件问题，无法测试
     * 原理：定义流程模型的时候，流程内的每个任务都可以添加监听器，可以监听
     *      Create：任务创建后触发
     *      Assignment：任务分配后触发
     *      Delete：任务完成后触发
     *      All：所有事件发生都触发
     *      监听器需要绑定一个实现了TaskListener接口的类，在创建任务、任务分配后、任务完成后、或者以上三个情形的时候就会执行类中的代码，去动态的指定或者获取一些东西。此类需要在定义模型的时候指定好全路径类名。
     */
    @Test
    public void testDeployment() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();

        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/demo-listen.bpmn") // 添加bpmn资源
                .name("监听器")
                .disableSchemaValidation()//禁用验证
                .deploy();

        System.out.println("流程ID：" + deployment.getId());
        System.out.println("流程名称：" + deployment.getName());
    }

    @Test
    public void testQueryTaskByAssignee(){
        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final TaskService taskService = processEngine.getTaskService();
        final RuntimeService runtimeService = processEngine.getRuntimeService();

        //获取任务
        final List<Task> tasks = taskService.createTaskQuery()
                .processDefinitionKey("evection")//指定流程
                .includeProcessVariables()
                .taskAssignee("zhangsan")
                .orderByTaskCreateTime().desc().list();


        for (Task task : tasks) {
            final String processInstanceId = task.getProcessInstanceId();
            final ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();



            System.out.println("----------------------------");
            System.out.println("流程实例id： " + task.getProcessInstanceId());
            System.out.println("任务id： " + task.getId());
            System.out.println("任务负责人： " + task.getAssignee());
            System.out.println("任务名称： " + task.getName());
            System.out.println("BusinessKey： " + processInstance.getBusinessKey());
        }


    }


    @Test
    public void completTask(){
        String assignee = "jerry";
        String processDefinitionKey = "evection";


        final ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        final TaskService taskService = processEngine.getTaskService();


        final List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).processDefinitionKey(processDefinitionKey).list();

        for (Task task : tasks) {
            System.out.println("任务名称："+task.getName());
        }
    }


}
